package com.szgz.platform.service;

import lombok.extern.slf4j.Slf4j;
import com.szgz.platform.util.MemoryParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class ResourceSchedulerService {

    @Value("${scheduler.max-containers:50}")
    private int maxContainers;

    @Value("${scheduler.max-memory-per-container:512m}")
    private String maxMemoryPerContainer;

    @Value("${scheduler.max-cpu-per-container:1}")
    private String maxCpuPerContainer;

    @Value("${scheduler.auto-scale-threshold:0.8}")
    private double autoScaleThreshold;

    // 资源使用统计
    private final AtomicInteger activeContainers = new AtomicInteger(0);
    private final Map<String, ContainerResource> containerResources = new ConcurrentHashMap<>();
    private final ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(5);

    /**
     * 容器资源信息
     */
    private static class ContainerResource {
        String containerId;
        String userId;
        String language;
        long memoryLimit;
        long cpuLimit;
        long startTime;
        long lastAccessTime;
        boolean isActive;

        ContainerResource(String containerId, String userId, String language, 
                        long memoryLimit, long cpuLimit) {
            this.containerId = containerId;
            this.userId = userId;
            this.language = language;
            this.memoryLimit = memoryLimit;
            this.cpuLimit = cpuLimit;
            this.startTime = System.currentTimeMillis();
            this.lastAccessTime = System.currentTimeMillis();
            this.isActive = true;
        }
    }

    /**
     * 资源分配请求
     */
    public static class ResourceRequest {
        private String userId;
        private String language;
        private int priority; // 1-10, 10为最高优先级
        private long estimatedMemory;
        private long estimatedCpu;

        public ResourceRequest(String userId, String language, int priority, 
                             long estimatedMemory, long estimatedCpu) {
            this.userId = userId;
            this.language = language;
            this.priority = priority;
            this.estimatedMemory = estimatedMemory;
            this.estimatedCpu = estimatedCpu;
        }

        // Getters
        public String getUserId() { return userId; }
        public String getLanguage() { return language; }
        public int getPriority() { return priority; }
        public long getEstimatedMemory() { return estimatedMemory; }
        public long getEstimatedCpu() { return estimatedCpu; }
    }

    /**
     * 资源分配结果
     */
    public static class ResourceAllocation {
        private boolean allocated;
        private String containerId;
        private String message;
        private long waitTime;

        public ResourceAllocation(boolean allocated, String containerId, 
                                String message, long waitTime) {
            this.allocated = allocated;
            this.containerId = containerId;
            this.message = message;
            this.waitTime = waitTime;
        }

        public static ResourceAllocation success(String containerId) {
            return new ResourceAllocation(true, containerId, "资源分配成功", 0);
        }

        public static ResourceAllocation failure(String message, long waitTime) {
            return new ResourceAllocation(false, null, message, waitTime);
        }

        // Getters
        public boolean isAllocated() { return allocated; }
        public String getContainerId() { return containerId; }
        public String getMessage() { return message; }
        public long getWaitTime() { return waitTime; }
    }

    /**
     * 请求资源分配
     */
    public ResourceAllocation requestResource(ResourceRequest request) {
        long startTime = System.currentTimeMillis();

        try {
            // 检查资源限制
            if (!checkResourceLimits(request)) {
                return ResourceAllocation.failure("资源不足，请稍后重试", 
                    System.currentTimeMillis() - startTime);
            }

            // 检查用户配额
            if (!checkUserQuota(request.getUserId())) {
                return ResourceAllocation.failure("用户配额已用完", 
                    System.currentTimeMillis() - startTime);
            }

            // 分配资源
            String containerId = allocateContainer(request);
            if (containerId != null) {
                // 记录资源使用
                recordResourceUsage(containerId, request);
                return ResourceAllocation.success(containerId);
            } else {
                return ResourceAllocation.failure("容器创建失败", 
                    System.currentTimeMillis() - startTime);
            }

        } catch (Exception e) {
            log.error("资源分配失败", e);
            return ResourceAllocation.failure("资源分配异常: " + e.getMessage(), 
                System.currentTimeMillis() - startTime);
        }
    }

    /**
     * 检查资源限制
     */
    private boolean checkResourceLimits(ResourceRequest request) {
        int currentContainers = activeContainers.get();
        
        // 检查容器数量限制
        if (currentContainers >= maxContainers) {
            log.warn("容器数量达到上限: {}", maxContainers);
            return false;
        }

        // 检查内存限制
        long totalMemory = getTotalMemoryUsage();
        long maxMemory = getMaxMemoryLimit();
        if (totalMemory + request.getEstimatedMemory() > maxMemory) {
            log.warn("内存使用达到上限: {}/{}", totalMemory, maxMemory);
            return false;
        }

        // 检查CPU限制
        double totalCpu = getTotalCpuUsage();
        double maxCpu = getMaxCpuLimit();
        if (totalCpu + request.getEstimatedCpu() > maxCpu) {
            log.warn("CPU使用达到上限: {}/{}", totalCpu, maxCpu);
            return false;
        }

        return true;
    }

    /**
     * 检查用户配额
     */
    private boolean checkUserQuota(String userId) {
        // 统计用户当前活跃容器数
        long userActiveContainers = containerResources.values().stream()
                .filter(cr -> cr.userId.equals(userId) && cr.isActive)
                .count();

        // 用户最多同时运行3个容器
        if (userActiveContainers >= 3) {
            log.warn("用户 {} 容器数量达到配额", userId);
            return false;
        }

        return true;
    }

    /**
     * 分配容器
     */
    private String allocateContainer(ResourceRequest request) {
        try {
            // 这里应该调用ContainerOrchestrationService创建容器
            // 暂时返回模拟的容器ID
            String containerId = "container_" + UUID.randomUUID().toString().substring(0, 8);
            
            // 增加活跃容器计数
            activeContainers.incrementAndGet();
            
            return containerId;
        } catch (Exception e) {
            log.error("容器分配失败", e);
            return null;
        }
    }

    /**
     * 记录资源使用
     */
    private void recordResourceUsage(String containerId, ResourceRequest request) {
        ContainerResource resource = new ContainerResource(
            containerId,
            request.getUserId(),
            request.getLanguage(),
            request.getEstimatedMemory(),
            request.getEstimatedCpu()
        );
        
        containerResources.put(containerId, resource);
        log.info("记录资源使用: containerId={}, userId={}, language={}", 
                containerId, request.getUserId(), request.getLanguage());
    }

    /**
     * 释放资源
     */
    public void releaseResource(String containerId) {
        ContainerResource resource = containerResources.remove(containerId);
        if (resource != null) {
            activeContainers.decrementAndGet();
            log.info("释放资源: containerId={}, userId={}", containerId, resource.userId);
        }
    }

    /**
     * 更新容器访问时间
     */
    public void updateContainerAccess(String containerId) {
        ContainerResource resource = containerResources.get(containerId);
        if (resource != null) {
            resource.lastAccessTime = System.currentTimeMillis();
        }
    }

    /**
     * 获取资源使用统计
     */
    public Map<String, Object> getResourceStats() {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("activeContainers", activeContainers.get());
        stats.put("maxContainers", maxContainers);
        stats.put("totalMemoryUsage", getTotalMemoryUsage());
        stats.put("maxMemoryLimit", getMaxMemoryLimit());
        stats.put("totalCpuUsage", getTotalCpuUsage());
        stats.put("maxCpuLimit", getMaxCpuLimit());
        stats.put("utilizationRate", getUtilizationRate());
        
        // 按语言统计
        Map<String, Long> languageStats = containerResources.values().stream()
                .filter(cr -> cr.isActive)
                .collect(HashMap::new, 
                    (map, cr) -> map.merge(cr.language, 1L, Long::sum), 
                    HashMap::putAll);
        stats.put("languageStats", languageStats);
        
        return stats;
    }

    /**
     * 自动扩缩容检查
     */
    public void checkAutoScaling() {
        double utilizationRate = getUtilizationRate();
        
        if (utilizationRate > autoScaleThreshold) {
            log.info("资源使用率过高: {}, 触发自动扩容", utilizationRate);
            // 这里可以实现自动扩容逻辑
            // 比如增加更多的容器实例或调整资源限制
        } else if (utilizationRate < autoScaleThreshold * 0.5) {
            log.info("资源使用率较低: {}, 可以考虑缩容", utilizationRate);
            // 这里可以实现自动缩容逻辑
        }
    }

    /**
     * 清理长时间未使用的容器
     */
    public void cleanupIdleContainers() {
        long currentTime = System.currentTimeMillis();
        long idleTimeout = 30 * 60 * 1000; // 30分钟
        
        containerResources.entrySet().removeIf(entry -> {
            ContainerResource resource = entry.getValue();
            if (resource.isActive && 
                (currentTime - resource.lastAccessTime) > idleTimeout) {
                log.info("清理空闲容器: {}", resource.containerId);
                activeContainers.decrementAndGet();
                return true;
            }
            return false;
        });
    }

    /**
     * 获取总内存使用量
     */
    private long getTotalMemoryUsage() {
        return containerResources.values().stream()
                .filter(cr -> cr.isActive)
                .mapToLong(cr -> cr.memoryLimit)
                .sum();
    }

    /**
     * 获取最大内存限制
     */
    private long getMaxMemoryLimit() {
        return MemoryParser.parseToBytes(maxMemoryPerContainer) * maxContainers;
    }

    /**
     * 获取总CPU使用量
     */
    private double getTotalCpuUsage() {
        return containerResources.values().stream()
                .filter(cr -> cr.isActive)
                .mapToDouble(cr -> cr.cpuLimit)
                .sum();
    }

    /**
     * 获取最大CPU限制
     */
    private double getMaxCpuLimit() {
        return Double.parseDouble(maxCpuPerContainer) * maxContainers;
    }

    /**
     * 获取资源利用率
     */
    private double getUtilizationRate() {
        double memoryUtilization = (double) getTotalMemoryUsage() / getMaxMemoryLimit();
        double cpuUtilization = getTotalCpuUsage() / getMaxCpuLimit();
        return Math.max(memoryUtilization, cpuUtilization);
    }

    /**
     * 启动定时任务
     */
    public void startScheduledTasks() {
        // 每5分钟检查一次自动扩缩容
        schedulerExecutor.scheduleAtFixedRate(
            this::checkAutoScaling, 5, 5, TimeUnit.MINUTES);
        
        // 每10分钟清理一次空闲容器
        schedulerExecutor.scheduleAtFixedRate(
            this::cleanupIdleContainers, 10, 10, TimeUnit.MINUTES);
    }

    /**
     * 关闭调度器
     */
    public void shutdown() {
        schedulerExecutor.shutdown();
        try {
            if (!schedulerExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
                schedulerExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            schedulerExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
} 